package com.navidove.appspotlight.model.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.navidove.appspotlight.model.bo.AppDevice;
import com.navidove.appspotlight.model.bo.AppItem;
import com.navidove.appspotlight.model.bo.SysImage;
import com.navidove.appspotlight.model.bo.AppDevice.DeviceType;
import com.navidove.appspotlight.model.dao.AppDeviceDao;
import com.navidove.appspotlight.model.dao.AppItemDao;
import com.navidove.appspotlight.model.dao.SysImageDao;
import com.navidove.appspotlight.model.service.AppItemService;
import com.navidove.appspotlight.model.service.SysImageService;
import com.navidove.commons.exception.DataDuplicatedException;
import com.navidove.commons.vo.Paging;

@Service
public class AppItemServiceImpl implements AppItemService {

	@Autowired
	private AppItemDao appItemDao;

	@Autowired
	private AppDeviceDao appDeviceDao;
	
	@Autowired
	private SysImageDao sysImageDao;
	
	@Autowired
	private SysImageService sysImageService;

	@SuppressWarnings("unchecked")
	public List<AppItem> getAppItemList(String appName, String owner,
			Long sourceId, Long categoryId, Boolean enable, Paging paging) {

		DetachedCriteria criteria = DetachedCriteria.forClass(AppItem.class, "ai");
		criteria.createAlias("appSource", "appSource");
		criteria.createAlias("appCategory", "appCategory");
		if (StringUtils.isNotBlank(appName)) {
			criteria.add(Restrictions.like("appName", "%" + appName + "%")
					.ignoreCase());
		}
		if (StringUtils.isNotBlank(owner)) {
			criteria.add(Restrictions.like("owner", "%" + owner + "%")
					.ignoreCase());
		}
		if (sourceId != null) {
			criteria.add(Restrictions.eq("appSource.id", sourceId));
		}
		if (categoryId != null) {
			criteria.add(Restrictions.eq("appCategory.id", categoryId));
		}
		if (Boolean.TRUE.equals(enable)) {
			criteria.add(Restrictions.eq("enable", Boolean.TRUE));
			
			DetachedCriteria subquery = DetachedCriteria.forClass(AppDevice.class, "appDevice");
			subquery.add(Restrictions.eq("enable", Boolean.TRUE));
			subquery.add(Restrictions.eqProperty("appDevice.appItem.id", "ai.id"));
			subquery.setProjection(Projections.id());
			criteria.add(Subqueries.exists(subquery));
		}

		return (List<AppItem>) appItemDao.getListByCriteria(criteria, paging);
	}

	public void saveAppItem(AppItem appItem) {
		// 檢查唯一
		appItemDao.clear();
		DetachedCriteria criteria = DetachedCriteria.forClass(AppItem.class);
		criteria.add(Restrictions.eq("appName", appItem.getAppName())
				.ignoreCase());
		if (appItem.getId() != null) {
			criteria.add(Restrictions.ne("id", appItem.getId()));
		}
		criteria.setProjection(Projections.rowCount());
		Number count = (Number) appItemDao.getByCriteria(criteria);
		if (count.intValue() > 0) {
			throw new DataDuplicatedException(AppItem.class.getName());
		}

		Date now = new Date();
		if (appItem.getId() == null) {
			appItem.setCrtAt(now);
		}
		appItem.setUpdAt(now);
		appItemDao.save(appItem);
	}
	
	public void deleteAppItem(Long id) {
		appDeviceDao.executeByQueryString("delete from AppDevice where appItem.id=?", id);
		appItemDao.executeByQueryString("delete from AppItem where id=?", id);
	}

	public AppItem getAppItem(Long id) {
		return appItemDao.get(id);
	}
	
	public AppItem getAppItem(String appName) {
		return appItemDao.get(Restrictions.eq("appName", appName));
	}

	public AppDevice getAppDevice(Long appItemId, DeviceType deviceType) {
		DetachedCriteria criteria = DetachedCriteria.forClass(AppDevice.class);
		criteria.add(Restrictions.eq("appItem.id", appItemId));
		criteria.add(Restrictions.eq("deviceType", deviceType));
		return (AppDevice) appDeviceDao.getByCriteria(criteria);
	}
	
	public List<AppDevice> getAppDeviceList(Long appItemId) {
		return appDeviceDao.getList(Restrictions.eq("appItem.id", appItemId));
	}
	
	public void saveAppDevice(AppDevice appDevice, MultipartFile qrcImageFile, MultipartFile iconImageFile) {
		Date now = new Date();
		
		SysImage qrcImage = sysImageService.saveSysImage(qrcImageFile);
		SysImage iconImage = sysImageService.saveSysImage(iconImageFile);
		
		if (appDevice.getId() == null) {
			appDevice.setCrtAt(now);
		}
		
		if (qrcImage != null) {
			appDevice.setQrcImage(qrcImage);
		}
		if (iconImage != null) {
			appDevice.setIconImage(iconImage);
		}
		
		appDevice.setUpdAt(now);
		appDeviceDao.save(appDevice);
	}
	
	public void deleteAppDevice(Long appItemId, DeviceType deviceType) {
		AppDevice d = appDeviceDao.get(Restrictions.eq("appItem.id", appItemId),
				Restrictions.eq("deviceType", deviceType));
		appDeviceDao.delete(d);
	}
}
